home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / sonido / aumix-0.000 / aumix-0 / aumix-0.2 / dbmeter.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-28  |  4.7 KB  |  174 lines

  1. /*
  2.  *  A simple DB meter program (experimental)
  3.  *
  4.  *  AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
  5.  */
  6.  
  7. /*   This program is free software; you can redistribute it and/or
  8.      modify it under the terms of the GNU General Public License
  9.      as published by the Free Software Foundation; either version 2
  10.      of the License, or (at your option) any later version.
  11.  
  12.      This program is distributed in the hope that it will be useful,
  13.      but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.      GNU General Public License for more details.
  16.  
  17.      You should have received a copy of the GNU General Public License
  18.      along with this program; if not, write to the Free Software
  19.      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <signal.h>
  25. #include <sys/types.h>
  26. #include <fcntl.h>
  27. #include <unistd.h>
  28. #include <sys/time.h>
  29.  
  30. #define BUF_SIZE 10000
  31. #define QUEUE_SIZE 1000
  32.  
  33. int queue[QUEUE_SIZE], front = 0, end = 0, write_lock;
  34.  
  35. void print_bar(int);
  36. void write_finished(int);
  37.  
  38. int main(int argc, char *argv[])
  39. {
  40.   char buf[BUF_SIZE];
  41.   int i, j, fd = 0, bytes_read, remain = 0, interval_size, first_enter = 1, temp;
  42.   struct itimerval value, ovalue = {0, 0, 0, 0};
  43.  
  44.   if (argc < 3 || argc > 4) {
  45.     fprintf(stderr, "\nUsage: dbmeter <infile> <samplerate> [outfile]\n");
  46.     exit(-1);
  47.   }
  48.  
  49.   /* Update meter every 1/10th second (every samplerate/10 samples) */
  50.   interval_size = atoi(argv[2]) / 10;
  51.  
  52.   if (strcmp("-", argv[1]))
  53.     if ((fd = open(argv[1], O_RDONLY, 0)) == -1) {
  54.       perror(argv[1]);
  55.       exit(-1);
  56.     }
  57.  
  58.   if ((bytes_read = read(fd, buf, BUF_SIZE)) == -1) {
  59.     perror(argv[1]);
  60.     exit(-1);
  61.   }
  62.   if (argc == 4 && !strcmp(argv[3], "-"))
  63.     write(1, buf, bytes_read);
  64.  
  65.   while (bytes_read) {
  66.     if (remain) {
  67.       for (i = 0; i < remain; i++)
  68.         temp += abs((unsigned char) buf[i]-0x80);
  69.       /* Wait until queue not full */
  70.       while ((end == QUEUE_SIZE && front == 0) || end == front-1);
  71.       queue[end++] = temp / interval_size;
  72.       end %= QUEUE_SIZE;
  73.     }
  74.     for (i = remain; i < bytes_read; i += interval_size) {
  75.       temp = 0;
  76.       for (j = 0; j < interval_size && (i+j) < bytes_read; j++)
  77.         temp += abs((unsigned char) buf[i+j]-0x80);
  78.       if (!(remain = interval_size - j)) {
  79.         /* Wait until queue not full */
  80.         while ((end == QUEUE_SIZE && front == 0) || end == front-1);
  81.         /* Save average amplitude in queue */
  82.         queue[end++] = temp / interval_size;
  83.         end %= QUEUE_SIZE;
  84.       }
  85.     }
  86.  
  87.     if (first_enter) {
  88.       first_enter = 0;
  89.       /* Schedule to update DB meter every 1/10th second */
  90.       value.it_interval.tv_sec = 0;
  91.       value.it_interval.tv_usec = 1000000 / 10;
  92.       value.it_value.tv_sec = 0;
  93.       value.it_value.tv_usec = 1000000 / 10;
  94.  
  95.       signal(SIGALRM, print_bar);
  96.       setitimer(ITIMER_REAL, &value, &ovalue);
  97.     }
  98.  
  99.     do {
  100.       bytes_read = read(fd, buf, BUF_SIZE);
  101.       if (bytes_read == -1 && errno != EINTR) {
  102.         perror(argv[1]);
  103.         exit(-1);
  104.       }
  105.     } while (bytes_read == -1 && errno == EINTR);
  106.     if (!strcmp(argv[3], "-")) {
  107.       write_lock = 1;               
  108.       signal(SIGCHLD, write_finished);
  109.       /* Write to standard output */
  110.       if (!fork()) {
  111.         /* Child */
  112.         if (write(1, buf, bytes_read) == -1) {
  113.           perror("stdout write");
  114.           exit(-1);
  115.         }
  116.         exit(0);
  117.       }
  118.       /* Wait for child to finish writing */
  119.       while(write_lock);
  120.     }
  121.   }  /* end while(bytes_read) */
  122.  
  123.   /* Wait for playing to finish */
  124.   while (front != end);
  125.   value.it_interval.tv_sec = 0;
  126.   value.it_interval.tv_usec = 0;
  127.   value.it_value.tv_sec = 0;
  128.   value.it_value.tv_usec = 0;
  129.   setitimer(ITIMER_REAL, &value, &ovalue);
  130.  
  131.   close(fd);
  132. }
  133.  
  134. /*
  135.  * Update DB meter (called every 1/10th second)
  136.  */
  137. void print_bar(int dummy)
  138. {
  139.   int i, value;
  140.   static prev_value = -1;
  141.  
  142.   if (front == end) {
  143.     fprintf(stderr, "\nqueue empty!\n");
  144.     exit(-1);
  145.   }
  146.  
  147.   /* Take saved average amplitude from queue and update DB meter */
  148.   value = queue[front++];
  149.   front %= QUEUE_SIZE;
  150.  
  151.   if (value != prev_value) {
  152.     prev_value = value;
  153.     if (value < 0 || value > 128)
  154.       fprintf(stderr, "Wrong!: %d        \n", value); /* Value out of range */
  155.  
  156.     fprintf(stderr, "%c[1;1H", 27);    /* home cursor */
  157.     for (i = 0; i < 80; i++)
  158.       if (i < value)
  159.         fprintf(stderr, "%c[1m#%c[0m", 27, 27);  /* print a '#' in bold */
  160.       else
  161.         fprintf(stderr, "#");    /* print a '#' unbolded */
  162.     fprintf(stderr, "\n");
  163.   }
  164.   signal(SIGALRM, print_bar);
  165. }
  166.  
  167. /*
  168.  * Release write lock when child finishes writing
  169.  */
  170. void write_finished(int dummy)
  171. {
  172.   write_lock = 0;
  173. }
  174.